//:C16:TPStash2.h
// Templatized PStash with nested iterator
#ifndef TPStash2_H__
#define TPStash2_H__
#include "../require.h"
#include <cstdlib>
template<class T, int incr = 20>
class PStash
{
    int quantity;
    int next;
    T **storage;
    void inflate(int increase = incr);
    public:
        PStash() : quantity(0), storage(0), next(0){} 
        ~PStash();
        int add(T *element);
        T * operator[](int index) const;
        T * remove(int index);
        int count() const{ return next; }
        // Nested iterator class:
        class iterator;    // Declaration required
        friend class iterator;    // Make it a friend                           
        class iterator                                  
        {
            // Now define it 
            PStash &ps;
            int index;
            public:
                iterator(PStash &pStash)
                    : ps(pStash), index(0){}
            // To create the end sentinel:
            iterator(PStash & pStash, bool)
                : ps(pStash), index(ps.next){}
            // Copy-constructor:
            iterator &operator= (const iterator &rv)
            {
                ps = rv.ps;
                index = rv.index;
                return *this;
            }
            iterator & operator++()
            {
                require(++index <= ps.next,
                    "PStash::iterator::operator++ "
                    "moves index out of bounds");
                return *this;
            }
            iterator & operator++(int)
            {
                return operator++();
            }
            iterator & operator--()
            {
                require(--index >= 0,
                    "moves index out of bounds");
                return *this;
            }
            iterator & operator--(int)
            {
                return operator--();
            }
            // Jump iterator forward or backward:
            iterator & operator+=(int amount)
            {
                require(index + amount < ps.next && 
                    index + amount >= 0,
                    "PStash::iterator:operator+= "
                    "attempt to index out of bounds");
                index += amount;
                return *this;
            }
            iterator & operator-=(int amount)
            {
                require(index - amount < ps.next && 
                    "PStash::iterator::operator-= "
                    "attempt to index out of bounds");
                index -= amount;
                return *this;
            }
            // Create a new iterator that's moved forward
            iterator operator+(int amount) const
            {
                iterator ret(*this);
                ret += amount;    // op+= does bounds check
                return ret;
            }
            T *current() const
            {
                return ps.storage[index];
            }
            T * operator*() const
            {
                return current();
            }
            T * operator->() const
            {
                require(ps.storage[index] != 0,
                    "PStash::iterator::operator->returns 0");
                return current();
            }
            // Remove the current element:
            T * remove()
            {
                return ps.remove(index);
            }
            // Comparison tests for end:
            bool operator==(const iterator &rv) const
            {
                return index == rv.index;
            }
            bool operator!=(const iterator &rv) const
            {
                return index != rv.index;
            }
        };
        iterator begin(){ return iterator(*this); }
        iterator end(){ return iterator(*this ,true); }
};
// Destruction of contained objects:
template<class T, int incr>
PStash<T, incr>::~PStash()
{
    for(int i = 0; i < next; i++)
    {
        delete storage[i];    // Null pointers OK
        storage[i] = 0;   // Just to be safe                         
    }
    delete []storage;
}
template<class T, int incr>
int PStash<T, incr>::add(T *element)

{
    if(next >= quantity)
    {
        inflate();
    }
    storage[next++] = element;
    return (next - 1);    // Index number
}
template<class T, int incr> inline
T *PStash<T, incr>::operator[](int index) const
{
    require(index >= 0,
        "PStash::operator[] index negative");
    return storage[index];
}
template<class T, int incr>
T *PStash<T, incr>::remove(int index)
{
    // operator[] performs validity checks:
    T *v = operator[](index);
    // "Remove" the pointer:
    storage[index] = 0;
    return v;
}
template<class T, int incr>
void PStash<T, incr>::inflate(int increase)
{
    const int tsz = sizeof(T*);
    T **st = new T*[quantity + increase];
    memset(st, 0, (quantity + increase));
    memcpy(st, storage, quantity * tsz);
    quantity += increase;
    delete []storage;    // Old storage
    storage = st;    // Point to new memory                                              
}
#endif
